﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Xml;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Utilities;
using InfoJetSoft.Service;
using ServBus.InfoBus2010.Extension;
using ServBus.InfoBus2010.License;
using ServBus.InfoBus2010.Utility;
using ServBus.InfoBus2010.Resources;
using FluentRibbon;
using FluentRibbon.Definitions;
using FluentRibbon.Libraries;
using FluentRibbon.Definitions.Controls;

namespace ServBus.InfoBus2010.ApplicationPages
{
    public partial class InfoBusServiceTest : RibbonLayoutsPage
    {
        public override TabDefinition GetTabDefinition()
        {
            return new TabDefinition()
            {
                Id = "TestRibbon",
                Title = "Test",
                Groups = new GroupDefinition[]
            {
                new GroupDefinition()
                {
                    Id = "TestGroup",
                    Title = "Test group",
                    Template = GroupTemplateLibrary.SimpleTemplate,
                    Controls = new ControlDefinition[]
                    {
                        new ButtonDefinition()
                        {
                            Id = "TestButton",
                            Title = "Test button",
                            CommandJavaScript = "alert('test!');",
                            Image = ImageLibrary.GetStandardImage(6, 0)
                        }
                    }
                }
            }

            };
        }

        private string _errorMsg;
        private string _xsnLocation;
        private SPWeb _currentWeb;
        private SPList _currentList;
        private ToolbarSettings _toolbarSettings;
        private License.License _license;
        private static DllResource Resource = new DllResource("ServBus.InfoBus2010.Common.Resources|AppPages");

        private bool IsNew
        {
            get
            {
                return !string.IsNullOrEmpty(Request.QueryString["XsnLocation"]);
            }
        }

        private void SetControlText()
        {
            this.ltCloseTop.Text = Resource.GetString("Btn_Close");
            this.ltCloseBottom.Text = Resource.GetString("Btn_Close");
            this.ltSaveTop.Text = Resource.GetString("Btn_Save");
            this.ltSaveBottom.Text = Resource.GetString("Btn_Save");
            this.ltSaveAsTop.Text = Resource.GetString("Btn_SaveAs");
            this.ltSaveAsBottom.Text = Resource.GetString("Btn_SaveAs");
            this.lbSaveDirectTop.Text = Resource.GetString("Btn_Save");
            this.lbSaveDirectBottom.Text = Resource.GetString("Btn_Save");
            this.ltPath.Text = Resource.GetString("Literal_Path");
            this.ltName.Text = Resource.GetString("Literal_Name");
            this.btnSave.Text = Resource.GetString("Btn_SaveInDlg");
            this.btnCancel.Text = Resource.GetString("Btn_CancelInDlg");
            this.cbOverwrite.Text = Resource.GetString("CheckBox_Overwrite");
            this.cbCloseAfterSave.Text = Resource.GetString("CheckBox_CloseAfterSave");
            this.ltSaveDlg.Text = Resource.GetString("Literal_SaveDlgTitle");

            if (Request.QueryString["XmlLocation"] != null)
            {
                string location = Request.QueryString["XmlLocation"];
                string filename = location.Substring(location.LastIndexOf('/') + 1);
                if (!IsPostBack)
                    this.tbName.Text = Path.GetFileNameWithoutExtension(filename);
                if (location.ToLower().StartsWith("http"))
                {
                    location = location.Substring(location.IndexOf('/', 9));
                }
                this.lblPath.Text = location.Substring(0, location.Length - filename.Length);
            }
            else if(Request.QueryString["SaveLocation"] != null)
            {
                string location = Request.QueryString["SaveLocation"];
                if (location.ToLower().StartsWith("http"))
                {
                    location = location.Substring(location.IndexOf('/', 9));
                }
                this.lblPath.Text = location.TrimEnd('/') + "/";
            }
        }

        protected void Page_Load(object sender, EventArgs e)
        {
            // Web & List
            _currentWeb = SPContext.Current.Web;

            string location = "";
            if (Request.QueryString["XmlLocation"] != null)
            {
                location = Request.QueryString["XmlLocation"];
                string filename = location.Substring(location.LastIndexOf('/') + 1);
                if (!IsPostBack)
                    this.tbName.Text = Path.GetFileNameWithoutExtension(filename);
                if (location.ToLower().StartsWith("http"))
                {
                    location = location.Substring(location.IndexOf('/', 9));
                }
                this.lblPath.Text = location.Substring(0, location.Length - filename.Length);
            }
            else if (Request.QueryString["SaveLocation"] != null)
            {
                location = Request.QueryString["SaveLocation"];
                if (location.ToLower().StartsWith("http"))
                {
                    location = location.Substring(location.IndexOf('/', 9));
                }
                this.lblPath.Text = location.TrimEnd('/') + "/";
            }
            _currentList = _currentWeb.GetList(location);

            _currentList = SPContext.Current.List;
            if (_currentList == null)
            {
                _errorMsg = Resource.GetString("Error_ListNotFound");
                return;
            }
            
            SetControlText();

            // Render
            if (!IsPostBack)
            {
                if (this.IsNew)
                {
                    // New
                    _xsnLocation = DecodeUrl.Decode(Request.QueryString["XsnLocation"]);

                    
                    this.ltListTitle.Text = "InfoBus 2010 - " + _currentList.Title;
                    if (!RegisterXsn())
                        return;

                    // Save Permission
                    if (!_currentList.DoesUserHavePermissions(SPBasePermissions.AddListItems))
                        _toolbarSettings.RemoveSave();

                    InfoJetContext ijCtx = new InfoJetContext();
                    ijCtx.InlineFileStorage = new InlineFileStorage();
                    RelativeUrlResolver resolver = new RelativeUrlResolver(_xsnLocation);
                    ijCtx.RelativeUrlResolver = resolver;
                    InfoJetForm newForm = InfoJetService.BuildFormByTemplate(Context, _xsnLocation, ijCtx);
                    this.lblForm.Text = newForm.Xhtml;

                }
                else
                {
                    // Open
                    string xmlLocation = Request.QueryString["XmlLocation"];
                    this.ltListTitle.Text = "InfoBus 2010 - " + Path.GetFileNameWithoutExtension(xmlLocation);
                    SPFile xmlFile = _currentWeb.GetFile(xmlLocation);
                    if (!xmlFile.Exists)
                    {
                        _errorMsg = Resource.GetString("Error_XmlNotFound");
                        return;
                    }

                    string xmlContent = GetXmlContent(xmlFile);
                    if (xmlContent == null)
                    {
                        _errorMsg = Resource.GetString("Error_XmlNotFound");
                        return;
                    }
                    _xsnLocation = GetXsnLocation(xmlFile);
                    if (!RegisterXsn())
                        return;

                    // Save Permission
                    if (!xmlFile.Item.DoesUserHavePermissions(SPBasePermissions.EditListItems))
                        _toolbarSettings.RemoveSave();

                    InfoJetContext ijCtx = new InfoJetContext();
                    ijCtx.InlineFileStorage = new InlineFileStorage();
                    RelativeUrlResolver resolver = new RelativeUrlResolver(_xsnLocation);
                    ijCtx.RelativeUrlResolver = resolver;
                    InfoJetForm editForm = InfoJetService.BuildFormByXML(Context, _xsnLocation, xmlContent, ijCtx);
                    this.lblForm.Text = editForm.Xhtml;
                }

                this.ViewState["XsnLocation"] = _xsnLocation;
            }
            else
            {
                LoadInfoFromViewState();
            }
        }

        private bool RegisterXsn()
        {
            Guid xsnId;
            byte[] xsnContent = GetXsnContent(_xsnLocation, out xsnId);
            if (xsnContent == null)
                return false;
            if (!ValidateInfoBus(xsnContent))
                return false;

            // Register
            bool succeed = false;
            string md5 = CryptoUtility.ComputeMD5(xsnContent);
            if (InfoJetService.GetMD5(_xsnLocation) == md5)
                return true;

            SPSecurity.RunWithElevatedPrivileges(() =>
            {
                using (SPSite adminSite = new SPSite(SPContext.Current.Site.ID))
                {
                    using (SPWeb adminWeb = adminSite.OpenWeb(SPContext.Current.Web.ID))
                    {
                        InfoJetContext ijCtx = new InfoJetContext();
                        ijCtx.Variables.Add("InfoBus_XsnId", xsnId.ToString());
                        ijCtx.ResourceFileStorage = new ResourceFileStorage(adminWeb);
                        ijCtx.InlineFileStorage = new InlineFileStorage();
                        if (!InfoJetService.RegisterWithMD5(Context, ijCtx, _xsnLocation, xsnContent, "", md5))
                        {
                            _errorMsg = Resource.GetString("Error_XsnLoadFail");
                            succeed = false;
                        }
                        else
                        {
                            succeed = true;
                        }
                    }
                }
            });
            return succeed;
        }

        private string GetXmlContent(SPFile xmlFile)
        {
            string xmlContent = null;
            if (_currentWeb.CurrentUser != null)
            {
                using (StreamReader reader = new StreamReader(xmlFile.OpenBinaryStream(), Encoding.UTF8))
                {
                    xmlContent = reader.ReadToEnd();
                }
            }
            else
            {
                if (xmlFile.Item.DoesUserHavePermissions(SPBasePermissions.ViewListItems))
                {
                    SPSecurity.RunWithElevatedPrivileges(() =>
                    {
                        using (SPSite adminSite = new SPSite(SPContext.Current.Site.ID))
                        {
                            using (SPWeb adminWeb = adminSite.OpenWeb(_currentWeb.ID))
                            {
                                SPFile adminFile = adminWeb.GetFile(xmlFile.ServerRelativeUrl);
                                xmlContent = Encoding.UTF8.GetString(adminFile.OpenBinary());
                            }
                        }
                    });
                }
            }
            return xmlContent;
        }

        private bool ValidateInfoBus(byte[] xsnContent)
        {
            // Validate InfoBus
            Activations activations = new Activations(SPContext.Current.Site.WebApplication);
            if (!activations.IsActivationValid(SPContext.Current.Web, out _errorMsg))
                return false;
            _license = LicenseContainer.ProductLicense;

            // Get Xsn
            XmlDocument xsfDoc = new XmlDocument();
            XsnExtractor extractor = new XsnExtractor(xsnContent);
            byte[] xsfContent = extractor.Extract("manifest.xsf");
            using (MemoryStream xsfStream = new MemoryStream(xsfContent))
            {
                xsfDoc.Load(xsfStream);
            }

            // Validate Feature
            FeatureChecker checker = new FeatureChecker(xsfDoc);
            _toolbarSettings = new ToolbarSettings(_currentList, checker);
            if (checker.HasManagedCode)
            {
                _errorMsg = Resource.GetString("Error_ManagedCodeNotSupport");
                return false;
            }
            if (_license.FeatureSet == FeatureSet.Lite || _license.FeatureSet == FeatureSet.Standard)
            {
                bool passCheck = true;
                if (!checker.BrowserCompatible)
                {
                    passCheck = false;
                }
                else
                {
                    // Check View
                    Dictionary<string, byte[]> views = extractor.Extract(checker.ViewXsls);
                    foreach (byte[] viewContent in views.Values)
                    {
                        if (ViewChecker.HasClientOnlyControls(viewContent))
                        {
                            passCheck = false;
                            break;
                        }
                    }
                }

                if (!passCheck)
                {
                    _errorMsg = Resource.GetString("Error_FeatureNotSupport");
                    return false;
                }
            }

            // Validate InfoJet
            InfoJetService.License(_license.InfoJetKey);

            _errorMsg = null;

            // Save to view state
            this.ViewState["ErrorMsg"] = _errorMsg;
            this.ViewState["License"] = _license;
            this.ViewState["Toolbar"] = _toolbarSettings;
            return true;
        }

        private void LoadInfoFromViewState()
        {
            _errorMsg = this.ViewState["ErrorMsg"] as string;
            _xsnLocation = this.ViewState["XsnLocation"] as string;
            _license = this.ViewState["License"] as License.License;
            _toolbarSettings = this.ViewState["Toolbar"] as ToolbarSettings;
        }

        private string GetXsnLocation(SPFile xmlFile)
        {
            return xmlFile.Item.ContentType.DocumentTemplateUrl;
        }

        private string GetXsnLocation(string xmlContent)
        {
            XmlDocument xmldoc = new XmlDocument();
            xmldoc.LoadXml(xmlContent);
            XmlNode piNode = xmldoc.SelectSingleNode("/processing-instruction(\"mso-infoPathSolution\")");
            XmlDocument piDoc = new XmlDocument();
            piDoc.LoadXml(string.Format("<pi {0}/>", piNode.Value));
            if (piDoc.DocumentElement.Attributes["href"] != null)
                return piDoc.DocumentElement.Attributes["href"].Value;
            else
                return null;
        }

        private MemoryStream SetXsnLocation(string xmlContent)
        {
            MemoryStream ms = new MemoryStream();
            XmlTextWriter xtw = new XmlTextWriter(ms, new System.Text.UTF8Encoding(false));
            xtw.Formatting = Formatting.None;
            XmlDocument xdoc = new XmlDocument();
            xdoc.LoadXml(xmlContent);
            XmlNode xn = xdoc.SelectSingleNode("/processing-instruction(\"mso-infoPathSolution\")");
            //替换处理指令value中的href属性
            string updateV = xn.Value.Substring(0, xn.Value.IndexOf("href") + 6) + _xsnLocation + "\"";
            xn.Value = updateV;
            xdoc.Save(xtw);
            return ms;
        }

        private byte[] GetXsnContent(string xsnLocation, out Guid xsnId)
        {
            byte[] result = null;
            xsnId = Guid.Empty;
            if (_currentWeb.CurrentUser != null)
            {
                SPFile xsnFile = _currentWeb.GetFile(xsnLocation);
                if (!xsnFile.Exists)
                {
                    _errorMsg = Resource.GetString("Error_XsnNotFound");
                    return null;
                }
                result = xsnFile.OpenBinary();
                xsnId = xsnFile.UniqueId;
            }
            else
            {
                Guid tempId = Guid.Empty;
                SPSecurity.RunWithElevatedPrivileges(() =>
                {
                    using (SPSite adminSite = new SPSite(SPContext.Current.Site.ID))
                    {
                        using (SPWeb adminWeb = adminSite.OpenWeb(_currentWeb.ID))
                        {
                            SPFile adminFile = adminWeb.GetFile(xsnLocation);
                            if (!adminFile.Exists)
                                _errorMsg = Resource.GetString("Error_XsnNotFound");
                            else
                            {
                                result = adminFile.OpenBinary();
                                tempId = adminFile.UniqueId;
                            }
                        }
                    }
                });
                xsnId = tempId;
            }
            return result;
        }

        protected void SaveDirect_Click(object sender, EventArgs e)
        {
            try
            {
                InfoJetContext ijCtx = new InfoJetContext();
                ijCtx.InlineFileStorage = new InlineFileStorage();
                InfoJetForm ipf = InfoJetService.ReloadForm(Context, ijCtx);
                lblForm.Text = ipf.Xhtml;
                SPWeb currentWeb = SPContext.Current.Web;
                SPFile file = currentWeb.GetFile(Request.QueryString["XmlLocation"]);
                MemoryStream ms = SetXsnLocation(ipf.Xml);
                file.SaveBinary(ms);
                ms.Close();
            }
            catch (Exception ex)
            {
                _errorMsg = ex.Message;
            }
        }

        protected void btnSave_Click(object sender, EventArgs e)
        {
            if (tbName.Text.Trim() == string.Empty)
            {
                lblSaveError.Text = Resource.GetString("Error_FileNameEmpty");
                lblSaveError.Visible = true;
                return;
            }

            try
            {
                InfoJetContext ijCtx = new InfoJetContext();
                ijCtx.InlineFileStorage = new InlineFileStorage();
                InfoJetForm ipf = InfoJetService.ReloadForm(Context, ijCtx);
                lblForm.Text = ipf.Xhtml;
                MemoryStream ms = SetXsnLocation(ipf.Xml);
                SPWeb currentWeb = SPContext.Current.Web;
                SPFolder folder = currentWeb.GetFolder(lblPath.Text);
                SPFile file = folder.Files.Add(tbName.Text.Trim() + ".xml", ms, cbOverwrite.Checked);
                ms.Close();

                lblSaveError.Text = string.Empty;
                lblSaveError.Visible = false;

                if (cbCloseAfterSave.Checked)
                {
                    SPUtility.Redirect(lblPath.Text, SPRedirectFlags.UseSource, Context);
                }
            }
            catch (Exception ex)
            {
                lblSaveError.Text = ex.Message;
                lblSaveError.Visible = true;
            }
        }

        protected override void OnPreRender(EventArgs e)
        {
            base.OnPreRender(e);
            StringBuilder jsBuilder = new StringBuilder();
            jsBuilder.AppendLine("<script type='text/javascript'>");

            if (!string.IsNullOrEmpty(_errorMsg))
            {
                jsBuilder.AppendLine(string.Format("showMessage(\"{0}\");", SPEncode.HtmlEncode(_errorMsg)));
            }
            if (lblSaveError.Visible)
            {
                jsBuilder.AppendLine("saveForm();");
            }

            if (_toolbarSettings != null)
            {
                if (_toolbarSettings.ShowTopToolbar)
                    jsBuilder.AppendLine("showThings('toolbarTop');");
                if (_toolbarSettings.ShowBottomToolbar)
                    jsBuilder.AppendLine("showThings('toolbarBottom');");
                if (_toolbarSettings.ShowBottomToolbar || _toolbarSettings.ShowTopToolbar)
                    jsBuilder.AppendLine("processToolBar(" + Convert.ToInt32(_toolbarSettings.ToolbarCommands) + ");");
            }

            if (_license != null && _license.LicenseType == LicenseType.Normal)
            {
                jsBuilder.AppendLine(string.Format("$(document.body).prepend(\"<img src='{0}' style='position:absolute;right:50px;top:50px'>\");",
                    this.ClientScript.GetWebResourceUrl(typeof(InfoBusServiceTest), "ServBus.InfoBus2010.ApplicationPages.Images.logoNormal.png")));
            }
            else
            {
                jsBuilder.AppendLine(string.Format("$(document.body).prepend(\"<img src='{0}' style='position:absolute;right:50px;top:50px'>\");",
                    this.ClientScript.GetWebResourceUrl(typeof(InfoBusServiceTest), "ServBus.InfoBus2010.ApplicationPages.Images.logoTrail.gif")));
            }

            jsBuilder.AppendLine("</script>");
            ltScript.Text = jsBuilder.ToString();
        }

        //protected void Refresh_Click(object sender, EventArgs e)
        //{
        //    InfoJetContext ijCtx = new InfoJetContext();
        //    ijCtx.InlineFileStorage = new InlineFileStorage();
        //    InfoJetForm ipf = InfoJetService.ReloadForm(Context, ijCtx);
        //    lblForm.Text = ipf.Xhtml;
        //}
    }
}
